﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace CTThrottling.Common
{
    /// <summary>
    /// IP地址帮助类
    /// </summary>
    public static class IpHelper
    {
        #region 将IP地址转换为整数
        /// <summary>
        /// 将IP地址转换为整数
        /// </summary>
        /// <param name="ip">待转换IP地址</param>
        /// <returns>转换结果</returns>
        public static int IpToInt(this string ip)
        {
            if (string.IsNullOrEmpty(ip) || !ip.IsIp())
            {
                return 0;
            }
            char[] dot = new char[] { '.' };
            string[] ipArr = ip.Split(dot);
            if (ipArr.Length == 3)
                ip = ip + ".0";
            ipArr = ip.Split(dot);

            int ip_Int = 0;
            int p1 = ipArr[0].ToInt32(0);
            int p2 = ipArr[1].ToInt32(0) * 256;
            int p3 = ipArr[2].ToInt32(0) * 256 * 256;
            int p4 = ipArr[3].ToInt32(0) * 256 * 256 * 256;
            ip_Int = p1 + p2 + p3 + p4;
            return ip_Int;
        }



        /// <summary>
        /// 将IP地址转换为长整数
        /// </summary>
        /// <param name="ip">待转换IP地址</param>
        /// <returns>转换结果</returns>
        public static long IpToLong(this string ip)
        {
            if (string.IsNullOrEmpty(ip) || !ip.IsIp())
            {
                return 0;
            }
            char[] dot = new char[] { '.' };
            string[] ipArr = ip.Split(dot);
            if (ipArr.Length == 3)
                ip = ip + ".0";
            ipArr = ip.Split(dot);

            long ip_Int = 0;
            long p1 = long.Parse(ipArr[0]) * 256 * 256 * 256;
            long p2 = long.Parse(ipArr[1]) * 256 * 256;
            long p3 = long.Parse(ipArr[2]) * 256;
            long p4 = long.Parse(ipArr[3]);
            ip_Int = p1 + p2 + p3 + p4;
            return ip_Int;
        }

        #endregion

        #region 将Int数据转换成IP字符串
        /// <summary>
        /// 将Int数据转换成IP字符串
        /// </summary>
        /// <param name="ip">Int数据</param>
        /// <returns>IP字符串</returns>
        public static string IntToIp(this int ip)
        {
            string sIP = "";
            uint t = 0;
            uint uip = (uint)ip;
            for (int i = 3; i >= 0; i--)
            {
                uint powIP = 1;
                for (int j = 0; j < i; j++)
                {
                    powIP *= 256;
                }
                t = uip / powIP;

                sIP = t.ToString() + "." + sIP;
                uip = uip - t * powIP;
            }
            sIP = sIP.Substring(0, sIP.Length - 1);
            return sIP;
        }
        #endregion

        #region 将Long数据转换成IP字符串
        /// <summary>
        /// 将Long数据转换成IP字符串
        /// </summary>
        /// <param name="ip_Int">Long格式IP</param>
        /// <returns>IP字符串</returns>
        public static string LongToIp(this long ip_Int)
        {
            long seg1 = (ip_Int & 0xff000000) >> 24;
            if (seg1 < 0)
                seg1 += 0x100;
            long seg2 = (ip_Int & 0x00ff0000) >> 16;
            if (seg2 < 0)
                seg2 += 0x100;
            long seg3 = (ip_Int & 0x0000ff00) >> 8;
            if (seg3 < 0)
                seg3 += 0x100;
            long seg4 = (ip_Int & 0x000000ff);
            if (seg4 < 0)
                seg4 += 0x100;
            string ip = seg1.ToString() + "." + seg2.ToString() + "." + seg3.ToString() + "." + seg4.ToString();

            return ip;
        }
        #endregion

        /// <summary>
        /// 是否为ip字符串
        /// </summary>
        /// <param name="ip">ip字符串</param>
        /// <returns>是否验证通过</returns>
        /// <example>
        /// <code lang="c#">
        /// <![CDATA[
        ///     
        ///     string ip="218.218.218.218";
        ///     bool ret=ip.IsIP(); //True
        /// ]]>
        /// </code>
        /// </example>
        public static bool IsIp(this string ip)
        {
            string pattrn = @"^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$";
            return Regex.IsMatch(ip, pattrn);
        }

        #region 将字符串转换为整数(int)

        /// <summary>
        /// 将字符串转换为数字(int)
        /// </summary>
        /// <param name="str">待转换字符</param>
        /// <param name="result">转换结果</param>
        ///  <param name="defaultval">转换失败时，返回默认值</param>
        /// <returns>转换是否成功</returns>
        /// <example>
        /// <code lang="c#">
        /// <![CDATA[
        ///     string str="abc";
        ///     int ret;
        ///     bool successed=str.TryToInt32(out ret); //false,ret=0;
        ///     
        ///     str="123";
        ///    successed=str.TryToInt32(out ret);   //true,ret=123;
        /// ]]>
        /// </code>
        /// </example>
        public static bool TryToInt32(this string str, out int result, int defaultval = 0)
        {
            result = defaultval;
            if (string.IsNullOrEmpty(str))
            {
                return false;
            }
            if (Int32.TryParse(str, out result))
            {
                return true;
            }
            result = defaultval;
            return false;
        }

        /// <summary>
        /// 将字符串转换为数字(int)
        /// </summary>
        /// <param name="str">待转换字符</param>
        ///  <param name="defaultval">转换失败时，返回默认值</param>
        /// <returns>返回转换后的值</returns>
        /// <example>
        /// <code lang="c#">
        /// <![CDATA[
        ///     string str="123";
        ///     int ret=str.ToInt32(0); //return 123
        ///     
        ///     str="abc";
        ///     ret=abc.ToInt32(); //return 0;
        /// ]]>
        /// </code>
        /// </example>
        public static int ToInt32(this string str, int defaultval = 0)
        {
            int result;
            str.TryToInt32(out result, defaultval);
            return result;
        }
        #endregion


    }

}
